package org.easier.framework.beancopier.cglib;

import org.easier.framework.beancopier.CopierAdapter;
import org.springframework.cglib.beans.BeanCopier;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class CachedBeanCopier implements CopierAdapter {

    private static volatile  Map<String, BeanCopier> BEAN_COPIERS = new HashMap<>();

    /**
     * 获取拷贝器
     * 如果缓存中有拷贝器则使用,
     * 没有则新建放入缓存返回
     *
     * @param srcClass
     * @param destClass
     * @return
     */
    private static BeanCopier getBeanCopier(Class srcClass, Class destClass) {
        String key = genKey(srcClass, destClass);
        BeanCopier copier;
        if (!BEAN_COPIERS.containsKey(key)) {
            copier = BeanCopier.create(srcClass, destClass, false);
            BEAN_COPIERS.put(key, copier);
        } else {
            copier = BEAN_COPIERS.get(key);
        }
        return copier;
    }

    private static String genKey(Class<?> srcClazz, Class<?> destClazz) {
        return srcClazz.getName() + destClazz.getName();
    }


    @Override
    public <T> T map(Object source, T target) {
        BeanCopier copier = getBeanCopier(source.getClass(), target.getClass());
        copier.copy(source, target, null);
        return target;
    }


    @Override
    public <T> T map(Object source, Class<T> targetClass) {
        T t = null;
        try {
            t = targetClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        //此处不使用转换器,类型不同时跳过,已由IAction.run实现
        BeanCopier copier = getBeanCopier(source.getClass(), targetClass);
        copier.copy(source, t, null);
        return t;
    }


    @Override
    public  <T> List<T> mapList(Object sources, Class<T> targetClass) {
        List<T> list = new ArrayList<>();
        if (sources instanceof List) {
            for (Object source : (List)sources) {
                list.add(map(source, targetClass));
            }
        }
        return list;
    }

}

